/*
	The MIT License

	Copyright (c) 2010 IFMO/GameDev Studio

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/


#pragma once

/*-----------------------------------------------------------------------------
	Scene node :
-----------------------------------------------------------------------------*/

class EScene : public IScene {
	public:
									EScene			( EGeometryFactory *ge );
									~EScene			( void );
		virtual IPxSceneNode		Root			( void ) { return root; }
		virtual const IPxSceneNode	Root			( void ) const { return root; }
		virtual void				WriteXML		( rapidxml::xml_node<> *xnode ) const;
		virtual void				ReadXML			( rapidxml::xml_node<> *xnode );
		
		virtual void				Clear			( void );
		virtual void				BreakHierarchy	( IPxSceneNode node );
	
		virtual IPxSceneIt			GetIterator		( ESceneIterType_s iter_type );
		virtual	IPxSceneNode		GetNodeByPath	( const char *path );
		
	protected:
		void	WriteXMLRecursive	( xml_node<> *xnode, const IPxSceneNode node ) const ;
		void	ReadXMLRecursive	( xml_node<> *xnode, IPxSceneNode node ) ;
	
		IPxSceneNode	root;
		EGeometryFactory	*ge;
	};
	
	
class ESceneIt : public ISceneIt {
	public:
								ESceneIt	( IPxSceneNode root, ESceneIterType_s type );
								~ESceneIt	( void );
	
		virtual void			Reset		( void );
		virtual bool			Done		( void );
		virtual void			Next		( void );
		virtual IPxSceneNode	Current		( void );
		
	protected:
		void		FillListRecursive		( IPxSceneNode node );
		void		FillListBFS				( IPxSceneNode root );
		void		FillListDFS				( IPxSceneNode root );
		bool		done;
		
		list<IPxSceneNode>::iterator	iter;
		list<IPxSceneNode>				sequence;
	};


class ESceneNode : public ISceneNode {
	public:
									ESceneNode		( EGeometryFactory *ge );
									~ESceneNode		( void );
					
		virtual IPxTriMesh			GetMesh			( void ) { return mesh; }
		virtual const IPxTriMesh	GetMesh			( void ) const { return mesh; }
		virtual void				SetMesh			( IPxTriMesh mesh ) { this->mesh = mesh; }

		virtual EString				GetScenePath	( void ) const;
		
		virtual EString				GetName			( void ) const { return name; }
		virtual void				SetName			( EString name ) { this->name = name; }
		virtual EString				GetPath			( void ) const;

		virtual EString				GetClass		( void ) const { return classname; }
		virtual void				SetClass		( EString classname ) { this->classname = classname; }

		virtual EString				GetAffector		( void ) const { return affector_str.c_str(); }
		virtual const char			*GetAffector	( const char *key, const char *def_value ) const;
		virtual void				SetAffector		( const char *affector_string );
		virtual void				AddAffector		( const char *affector_string );

		virtual void				GetLocalPose	( EPoint &pos, EQuaternion &orient ) const;
		virtual void				SetLocalPose	( const EPoint &pos, const EQuaternion &orient );
		virtual void				GetGlobalPose	( EPoint &pos, EQuaternion &orient ) const;

		//	hierarchy stuff :
		virtual void				AttachChild		( IPxSceneNode node );
		virtual void				DetachChild		( IPxSceneNode node );		
		virtual void				DetachChild		( uint index );	
		virtual void				DetachAll		( void );
		
		virtual uint				GetChildNum		( void ) const;
		virtual IPxSceneNode		GetChild		( uint index );
		virtual const IPxSceneNode	GetChild		( uint index ) const;
		virtual IPxSceneNode		GetChild		( EString name );
		virtual const IPxSceneNode	GetChild		( EString name ) const;
		
		virtual void				SetParent		( IPxSceneNode parent );
		virtual IPxSceneNode		GetParent		( void ) { return parent; }
		virtual const IPxSceneNode	GetParent		( void ) const { return parent; }

		//	xml stuff :
		virtual void				WriteXML		( rapidxml::xml_node<> *xnode ) const;
		virtual void				ReadXML			( rapidxml::xml_node<> *xnode );
		
		
	protected:
		EGeometryFactory	*ge;
		
		std::vector<IPxSceneNode>	children;
		IPxSceneNode			parent;
	
		IPxTriMesh		mesh;
		EString			name;
		EString			classname;
		EArgs			affector;
		std::string		affector_str;
		
		EQuaternion		orient;
		EPoint		position;
	};